home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
machserver
/
1.098
/
raid
/
devDebug.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-27
|
11KB
|
420 lines
/*
* devDebug.c --
*
* This module implements the BlockDevice interface for a device
* which echos requests to stdout.
*
* Copyright 1989 Regents of the University of California
* All rights reserved.
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#include "sync.h"
#include <sprite.h>
#include <stdio.h>
#include <stdlib.h>
#include "fs.h"
#include "devRaid.h"
#include "devBlockDevice.h"
#include "schedule.h"
#include "timer.h"
#include "devRaidProto.h"
typedef struct DebugHandle {
DevBlockDeviceHandle blockHandle; /* Must be FIRST field. */
Fs_Device *devPtr; /* Device corresponding to handle */
} DebugHandle;
#ifdef TESTING
/*
* Storage for contents of simulated disks.
* (16 disks of 32 bytes each)
*/
static char devDebugData[4][4][32] = {
"A0A1A2A3A4A5A6A7a0a1a2a3a4a5a6a7",
"B0B1B2B3B4B5B6B7b0b1b2b3b4b5b6b7",
"C0C1C2C3C4C5C6C7c0c1c2c3c4c5c6c7",
"D0D1D2D3D4D5D6D7d0d1d2d3d4d5d6d7",
"E0E1E2E3E4E5E6E7e0e1e2e3e4e5e6e7",
"F0F1F2F3F4F5F6F7f0f1f2f3f4f5f6f7",
"G0G1G2G3G4G5G6G7g0g1g2g3g4g5g6g7",
"H0H1H2H3H4H5H6H7h0h1h2h3h4h5h6h7",
"I0I1I2I3I4I5I6I7i0i1i2i3i4i5i6i7",
"J0J1J2J3J4J5J6J7j0j1j2j3j4j5j6j7",
"K0K1K2K3K4K5K6K7k0k1k2k3k4k5k6k7",
"L0L1L2L3L4L5L6L7l0l1l2l3l4l5l6l7",
"M0M1M2M3M4M5M6M7m0m1m2m3m4m5m6m7",
"N0N1N2N3N4N5N6N7n0n1n2n3n4n5n6n7",
"O0O1O2O3O4O5O6O7o0o1o2o3o4o5o6o7",
"P0P1P2P3P4P5P6P7p0p1p2p3p4p5p6p7",
};
static char logData[30000];
#endif
/*
* Forward Declarations.
*/
static ReturnStatus BlockIOProc();
static ReturnStatus BlockIOProc1();
static ReturnStatus ReleaseProc();
static ReturnStatus IOControlProc();
/*
*----------------------------------------------------------------------
*
* DevDebugAttach --
*
* Attach a Debug logical device to the system.
*
* Results:
* The DevBlockDeviceHandle of the device.
*
* Side effects:
* Modifies Debug data structure.
*
*----------------------------------------------------------------------
*/
DevBlockDeviceHandle *
DevDebugAttach(devicePtr)
Fs_Device *devicePtr; /* The device to attach. */
{
DebugHandle *handlePtr;
handlePtr = (DebugHandle *) malloc(sizeof(DebugHandle));
if (devicePtr->unit < 200) {
handlePtr->blockHandle.blockIOProc = BlockIOProc;
} else {
handlePtr->blockHandle.blockIOProc = BlockIOProc1;
}
handlePtr->blockHandle.releaseProc = ReleaseProc;
handlePtr->blockHandle.IOControlProc = IOControlProc;
if (devicePtr->unit == 99) {
handlePtr->blockHandle.minTransferUnit = 64;
} else {
handlePtr->blockHandle.minTransferUnit = 1;
}
handlePtr->blockHandle.maxTransferSize = 1<<30;
handlePtr->devPtr = devicePtr;
return (DevBlockDeviceHandle *) handlePtr;
}
/*
*----------------------------------------------------------------------
*
* ReleaseProc --
*
* Block device release proc.
*
* Results:
* Return status.
*
* Side effects:
*
*----------------------------------------------------------------------
*/
/*ARGUSED*/
static ReturnStatus
ReleaseProc(handlePtr)
DebugHandle *handlePtr; /* Handle pointer of device. */
{
free((char *) handlePtr);
return SUCCESS;
}
/*
*----------------------------------------------------------------------
*
* IOControlProc --
*
* Do a special operation on a raw SCSI Disk.
*
* Results:
* None.
*
* Side effects:
* Depends on operation.
*
*----------------------------------------------------------------------
*/
/*ARGSUSED*/
static ReturnStatus
IOControlProc(blockDevHandlePtr, ioctlPtr, replyPtr)
DevBlockDeviceHandle
*blockDevHandlePtr; /* Handle of the device to operate on. */
Fs_IOCParam *ioctlPtr; /* Standard I/O Control parameter block */
Fs_IOReply *replyPtr; /* outBuffer length and returned signal */
{
return SUCCESS;
}
/*
*----------------------------------------------------------------------
*
* BlockIOProc --
*
* Perform block IO on specified Debug device.
* Note that this procedure directly calles the callback procedure
* before returning.
*
* Results:
* The return code from the I/O operation.
*
* Side effects:
* Modifies devDebugData (i.e. the simulated disk contents) if
* TESTING is defined and the operation is a write.
*
*----------------------------------------------------------------------
*/
static ReturnStatus
BlockIOProc(handlePtr, requestPtr)
DevBlockDeviceHandle *handlePtr; /* Handle pointer of device. */
DevBlockDeviceRequest *requestPtr; /* IO Request to be performed. */
{
DebugHandle *debugHandlePtr = (DebugHandle *) handlePtr;
/*
* Debug device with unit number == 101 is the same as /dev/null except
* that you can also read infinite amounts of garbage from it as well
* as writing to it.
*/
if (debugHandlePtr->devPtr->unit < 100) {
printf("\nBlockIOProc\n");
PrintTime();
PrintHandle(handlePtr);
PrintDevice(debugHandlePtr->devPtr);
PrintRequest(requestPtr);
}
#ifdef TESTING
{
DevBlockDeviceRequest *localRequestPtr = requestPtr;
ReturnStatus status;
int row, col;
char **statusCtrl;
int i;
if (debugHandlePtr->devPtr->unit == 99) {
int *iBuf;
if (requestPtr->operation == FS_READ) {
bcopy(logData+requestPtr->startAddress,
requestPtr->buffer,requestPtr->bufferLen);
} else {
bcopy(requestPtr->buffer,
logData+requestPtr->startAddress,
requestPtr->bufferLen);
}
printf("XFER: ");
iBuf = (int *) requestPtr->buffer;
for (i = 0; i < requestPtr->bufferLen/4; i++) {
printf("%d ", iBuf[i]);
}
printf("\n");
requestPtr->doneProc(requestPtr, SUCCESS, requestPtr->bufferLen);
return SUCCESS;
}
row = debugHandlePtr->devPtr->unit/10;
col = debugHandlePtr->devPtr->unit%10;
if (requestPtr->operation == FS_READ) {
bcopy(devDebugData[row][col]+requestPtr->startAddress,
requestPtr->buffer,requestPtr->bufferLen);
} else {
bcopy(requestPtr->buffer,
devDebugData[row][col]+requestPtr->startAddress,
requestPtr->bufferLen);
}
printf("XFER: ");
printf("\"");
for (i = 0; i < requestPtr->bufferLen; i++) {
printf("%c", (char)
(requestPtr->buffer[i] == '\0' ? '_' : requestPtr->buffer[i]));
}
printf("\"");
printf("\n");
statusCtrl = (char **) requestPtr->ctrlData[0];
if (statusCtrl == (char **) NIL) {
status = SUCCESS;
} else {
status = (*(*statusCtrl)++ == 's' ? SUCCESS: FAILURE);
}
(void) printf("status: %d\n", status);
if (Spawn("disk") == 0) {
Delay(10.0);
localRequestPtr->doneProc(localRequestPtr,
status, localRequestPtr->bufferLen);
Terminate();
} else {
return SUCCESS;
}
}
#else
requestPtr->doneProc(requestPtr, SUCCESS, requestPtr->bufferLen);
return SUCCESS;
#endif TESTING
}
/*
*----------------------------------------------------------------------
*
* timerCallBackProc --
*
* Callback procedure for BlockIOProc1.
* This callback procedure called from timer interrupts which
* simulate IO interrupts that an IO to a real device would result in.
*
* Results:
* The return code from the I/O operation.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
#ifndef TESTING
typedef struct TimerCallBackData {
Timer_QueueElement *timerQueueElemPtr;
void (*proc)();
DevBlockDeviceRequest *requestPtr;
ReturnStatus status;
int amountTransferred;
} TimerCallBackData;
static void
timerCallBackProc(time, timerCallBackDataPtr)
Timer_Ticks time;
TimerCallBackData *timerCallBackDataPtr;
{
timerCallBackDataPtr->proc(timerCallBackDataPtr->requestPtr,
timerCallBackDataPtr->status, timerCallBackDataPtr->amountTransferred);
free((char*) timerCallBackDataPtr->timerQueueElemPtr);
free((char*) timerCallBackDataPtr);
}
#endif TESTING
/*
*----------------------------------------------------------------------
*
* BlockIOProc1 --
*
* Perform block IO on specified Debug device.
* This procedure is similar to BlockIOProc except that the callback
* is done at interrupt level via timer interrupts.
*
* Results:
* The return code from the I/O operation.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static ReturnStatus
BlockIOProc1(handlePtr, requestPtr)
DevBlockDeviceHandle *handlePtr; /* Handle pointer of device. */
DevBlockDeviceRequest *requestPtr; /* IO Request to be performed. */
{
#ifdef TESTING
DevBlockDeviceRequest *localRequestPtr = requestPtr;
DebugHandle *debugHandlePtr = (DebugHandle *) handlePtr;
ReturnStatus status;
char **statusCtrl;
int row, col;
int i;
printf("\nBlockIOProc\n");
PrintTime();
PrintHandle(handlePtr);
PrintDevice(debugHandlePtr->devPtr);
PrintRequest(requestPtr);
row = debugHandlePtr->devPtr->unit/10;
col = debugHandlePtr->devPtr->unit%10;
if (requestPtr->operation == FS_READ) {
bcopy(devDebugData[col][row],requestPtr->buffer,requestPtr->bufferLen);
} else {
bcopy(requestPtr->buffer,devDebugData[col][row],requestPtr->bufferLen);
}
printf("XFER: ");
for (i = 0; i < requestPtr->bufferLen; i++) {
printf("%c", (char) requestPtr->buffer[i]);
}
printf("\n");
/*
* When using the Debug device, ctrlData should be initialized with
* status control information.
*/
statusCtrl = (char **) requestPtr->ctrlData[0];
status = (*(*statusCtrl)++ == 's' ? SUCCESS: FAILURE);
(void) printf("status: %d\n", status);
/*
* Simulate request queueing.
*/
if (Spawn("disk")) {
return SUCCESS;
} else {
/*
* Child simulates IO Device.
*/
Delay(100.0);
localRequestPtr->buffer[0] =
debugHandlePtr->devPtr->unit/10+'0';
localRequestPtr->buffer[1] =
debugHandlePtr->devPtr->unit%10+'0';
localRequestPtr->doneProc(localRequestPtr,
status, localRequestPtr->bufferLen);
Terminate();
/*
* This never gets executed and is only here to shutup lint.
*/
return SUCCESS;
}
#else
{
Timer_QueueElement *timerQueueElemPtr;
TimerCallBackData *timerCallBackDataPtr;
timerQueueElemPtr = (Timer_QueueElement *)
malloc(sizeof(Timer_QueueElement));
timerCallBackDataPtr = (TimerCallBackData *)
malloc(sizeof(TimerCallBackData));
timerQueueElemPtr->routine = timerCallBackProc;
timerQueueElemPtr->clientData = (ClientData) timerCallBackDataPtr;
timerQueueElemPtr->interval = 10;
timerCallBackDataPtr->timerQueueElemPtr = timerQueueElemPtr;
timerCallBackDataPtr->proc = requestPtr->doneProc;
timerCallBackDataPtr->requestPtr = requestPtr;
timerCallBackDataPtr->status = SUCCESS;
timerCallBackDataPtr->amountTransferred = requestPtr->bufferLen;
Timer_ScheduleRoutine(timerQueueElemPtr, TRUE);
return SUCCESS;
}
#endif TESTING
}